#pragma once
#include "data/Example.h"

class HingeLoss
{
protected:
  const Example& m_Example;
public:
  HingeLoss(const Example& example)
    : m_Example(example)
  {
  }

  double operator() (const arma::sp_mat& weight, double bias)
  {
    double output = arma::dot(weight, m_Example.GetInput()) + bias;
    return std::max(1-output*m_Example.GetLabel(), 0.0);
  }

  void grad(const arma::sp_mat& weight, double bias, arma::sp_mat& weightGrad, double& biasGrad )
  {
    double output = m_Example.GetLabel() * (arma::dot(weight, m_Example.GetInput()) + bias);
    if (output < 1) {
      weightGrad = -m_Example.GetLabel() * m_Example.GetInput();
      biasGrad = -m_Example.GetLabel();
    }
    else {
      weightGrad.zeros(weight.n_rows, weight.n_cols);
      biasGrad = 0;
    }
  }
};

